/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com 

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 

#include "entityparser.h"


namespace tri{

tri::TVector parseVector(tri::TXMLNode* node){
	tri::TVector v;
	v.x  = node->getAttribute<float>("x");
	v.y  = node->getAttribute<float>("y");
	v.z  = node->getAttribute<float>("z");
	return v;
}

tri::graphics::TColor parseColor(tri::TXMLNode* node){
	int r  = node->getAttribute<int>("r");
	int g  = node->getAttribute<int>("g");
	int b  = node->getAttribute<int>("b");
	int a  = node->hasAttribute("a") ? node->getAttribute<int>("a") : 255;
	return tri::graphics::TColor(r, g, b, a);
}

void parseEntityConfigs(tri::TEntity* ent, tri::TXMLNode* node){
	if (node->hasElement("size")){
		ent->setSize( parseVector( node->getElement("size") ));
	}
	
	if (node->hasElement("scale")){
		ent->setScale( parseVector( node->getElement("scale") ));
	}
	
	if (node->hasElement("color")){
		ent->setColor( parseColor( node->getElement("color") ).asRGBA());
	}
}

tri::TEntity* parseEntity(tri::TXMLNode* node){
	tri::TEntity* ent = NULL;
	
	if (node->hasAttribute("type")){
		std::string str_type  = node->getAttribute<std::string>("type");
		if(str_type=="MODEL"){
			ent = new tri::TModel3D();
			
			if (node->hasAttribute("file")){
				((tri::TModel3D*)ent)->setModel(node->getAttribute<std::string>("file"));
			}else{
				tri::LOG_SEVERE("TEntity of type \"MODEL\" must contain a \"file\" attribute!!!");
				tri::utils::quit();
			}
			
			if (node->hasAttribute("image")){
				((tri::TModel3D*)ent)->setModelTexture(node->getAttribute<std::string>("image"));
			}
			
			if (node->hasElement("offsetPos")){
				((tri::TModel3D*)ent)->setOffsetPosition( parseVector( node->getElement("offsetPos") ));
			}
			
			if (node->hasElement("offsetRot")){
				((tri::TModel3D*)ent)->setOffsetRotation( parseVector( node->getElement("offsetRot") ));
			}
			
		}else if(str_type=="SPHERE"){
			ent = new tri::TSphere();
		}else if(str_type=="BOX"){
			ent = new tri::TCube();
		}else{
			tri::LOG_SEVERE("Attribute \"type\" value not valid!!!");
			tri::utils::quit();
		}
	}else{
		tri::LOG_SEVERE("TEntity node must contain an \"type\" attribute!!!");
		tri::utils::quit();
	}
	
	parseEntityConfigs(ent, node);
	return ent;
}

tri::TSimulationEntity* parseSimualtionEntity(tri::TXMLNode* node){
	
	int int_type;
	float mass=0;
	tri::TEntity* ent = NULL;
	
	if (node->hasAttribute("type")){
		std::string str_type  = node->getAttribute<std::string>("type");
		if(str_type=="BOX"){
			int_type = tri::PHYSICS_BOX;
		}else if(str_type=="CYLINDER"){
			int_type = tri::PHYSICS_CYLINDER;
		}else if(str_type=="SPHERE"){
			int_type = tri::PHYSICS_SPHERE;
		}else{
			tri::LOG_SEVERE("Attribute \"type\" value not valid!!!");
			tri::utils::quit();
		}
	}else{
		tri::LOG_SEVERE("TSimulationEntity node must contain an \"type\" attribute!!!");
		tri::utils::quit();
	}
	
	if (node->hasElement("TEntity")){
		ent = parseEntity(node->getElement("TEntity"));
	}else{
		tri::LOG_SEVERE("TSimulationEntity node must contain an \"TEntity\" element!!!");
		tri::utils::quit();
	}
	mass = node->hasAttribute("mass") ? node->getAttribute<float>("mass") : 0.0;
	
	tri::TSimulationEntity* sim_ent = new tri::TSimulationEntity();
	sim_ent->setGraphicComponent(ent, int_type, mass);
	return sim_ent;
}


tri::TEntity* loadEntityFromXML(std::string xmlfile){
	tri::TXMLDoc doc;
	doc.load(xmlfile.c_str());
	
	if(doc.hasElement("TEntity")){
		return parseEntity(doc.getElement("TEntity"));
	}else{
		tri::LOG_WARNING(xmlfile + " does not contain an TElement tag.");
	}
	
	return NULL;
}

tri::TSimulationEntity* loadSimulationEntityFromXML(std::string xmlfile){
	tri::TXMLDoc doc;
	doc.load(xmlfile.c_str());
	
	if(doc.hasElement("TSimulationEntity")){
		return parseSimualtionEntity(doc.getElement("TSimulationEntity"));
	}else{
		tri::LOG_WARNING(xmlfile + " does not contain an TSimulationEntity tag.");
	}
	
	return NULL;
}
}